package com.junyidao.game.util;

import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Created by zzh on 2016/9/26.
 * 文件描述 ：
 */
public class NumUtils {
    public static final String NAN = "NaN";
    private static Random r = new Random();

    /**
     * 生成一个从随机数
     *
     * @param from 包含
     * @param to   不包含
     * @return
     */
    public static int nextInt(int from, int to) {
        int left = to - from;
        int n = r.nextInt(left);
        return from + n;
    }

    /*
     * Long类型默认为O
     */
    public static Long defaultLong(Long obj) {
        if (obj == null) {
            return 0L;
        } else {
            return obj;
        }
    }

    /*
     * Integer类型默认为0
     */
    public static Integer defaultInteger(Integer obj) {
        if (obj == null) {
            return 0;
        } else {
            return obj;
        }
    }

    public static Long parseLong(String value) {
        if (null == value || NAN.equals(value)) {
            return null;
        }
        return Long.parseLong(value);
    }

    public static Double parseDouble(String value) {
        if (StringUtils.isEmpty(value) || NAN.equals(value)) {
            return null;
        }
        return Double.parseDouble(value);
    }

    public static Integer parseInt(String value) {
        if (StringUtils.isEmpty(value) || NAN.equals(value)) {
            return null;
        }
        return Integer.parseInt(value);
    }


    public static List<Integer> parseInt(String[] value) {
        List<Integer> result = new ArrayList<>();
        for (String s : value) {
            result.add(parseInt(s));
        }
        return result;
    }

    /**
     * 针对数字的值进行比较，无视数字的类型。可以是封装类型，也可以是原始类型
     *
     * @param n1
     * @param n2
     * @return 值相等返回true。同为null也返回true。一个为null，一个不是返回false
     * @author youxia
     */
    public static boolean isEqual(Number n1, Number n2) {
        if (n1 == null && n2 == null) {
            return true;
        }
        if (n1 == null || n2 == null) {
            return false;
        }
        if (isFloat(n1) || isFloat(n2)) {
            return n1.doubleValue() == n2.doubleValue();
        }
        return n1.longValue() == n2.longValue();
    }

    private static Double getDouble(Object o) {
        Double d;
        if (o instanceof String) {
            String sn1 = (String) o;
            d = Double.parseDouble(sn1);
        } else {
            Number nn1 = (Number) o;
            d = nn1.doubleValue();
        }
        return d;
    }

    /**
     * 支持String类型的比较
     *
     * @param n1
     * @param n2
     * @return 值相等返回true。同为null也返回true。一个为null，一个不是返回false
     * @author youxia
     */
    public static boolean isEqual(Object n1, Object n2) {
        if (n1 == null && n2 == null) {
            return true;
        }
        if (n1 == null || n2 == null) {
            return false;
        }
        if ((!(n1 instanceof String) && !(n1 instanceof Number) || !(n2 instanceof String) && !(n2 instanceof Number))) {
            return false;
        }
        try {
            Double d2 = getDouble(n2);
            Double d1 = getDouble(n1);
            return d1.doubleValue() == d2.doubleValue();
        } catch (NumberFormatException e) {
            return false;
        }
    }

    /**
     * 判定两个数字是否不等
     *
     * @param n1
     * @param n2
     * @return
     */
    public static boolean isNotEqual(Number n1, Number n2) {
        return !isEqual(n1, n2);
    }

    /**
     * 小于，null当作0
     *
     * @param n1
     * @param n2
     * @return
     */
    public static boolean lt(Number n1, Number n2) {
        if (null == n1)
            n1 = 0;
        if (null == n2)
            n2 = 0;
        return n1.doubleValue() < n2.doubleValue();
    }

    /**
     * 小于等于，null当作0
     *
     * @param n1
     * @param n2
     * @return
     */
    public static boolean le(Number n1, Number n2) {
        if (null == n1)
            n1 = 0;
        if (null == n2)
            n2 = 0;
        return n1.doubleValue() <= n2.doubleValue();
    }

    /**
     * 大于，null当作0
     *
     * @param n1
     * @param n2
     * @return
     */
    public static boolean gt(Number n1, Number n2) {
        if (null == n1)
            n1 = 0;
        if (null == n2)
            n2 = 0;
        return n1.doubleValue() > n2.doubleValue();
    }

    /**
     * 大于等于，null当作0
     *
     * @param n1
     * @param n2
     * @return
     */
    public static boolean ge(Number n1, Number n2) {
        if (null == n1)
            n1 = 0;
        if (null == n2) {
            n2 = 0;
        }
        return n1.doubleValue() >= n2.doubleValue();
    }

    private static boolean isFloat(Number n1) {
        return Double.class.isInstance(n1) || Float.class.isInstance(n1);
    }


    /**
     * 多个浮点数连加，解决精度问题
     *
     * @param nums
     * @return
     */
    public static Double add(Number... nums) {

        if (nums.length == 0)
            return 0.0;
        if (nums.length == 1) {
            return nums[0].doubleValue();
        }

        BigDecimal result = new BigDecimal(0);

        for (Number n : nums) {
            //null值视为0
            if (null == n) {
                n = 0;
            }
            //如果有参数为0，则结果为0；
            if (0 == n) {
                return 0.0;
            }
            result = result.add(new BigDecimal(n.toString()));

        }

        return result.doubleValue();

    }

    /**
     * 两数相减
     *
     * @param n1
     * @param n2
     * @return
     */
    public static Double subtract(Number n1, Number n2) {
        if (n1 == null) {
            n1 = 0.0;
        }
        if (n2 == null) {
            n2 = 0.0;
        }

        BigDecimal num1 = new BigDecimal(n1.toString());
        BigDecimal num2 = new BigDecimal(n2.toString());

        return num1.subtract(num2).doubleValue();

    }

    /**
     * 两数相除
     *
     * @param n1
     * @param n2
     * @return
     */
    public static Double divide(Number n1, Number n2) {
        if (n1 == null) {
            n1 = 0.0;
        }
        if (n2 == null) {
            n2 = 1.0;//除法，如果除数为空，则默认为1
        }

        BigDecimal num1 = new BigDecimal(n1.toString());
        BigDecimal num2 = new BigDecimal(n2.toString());
        return num1.divide(num2).doubleValue();

    }

    /**
     * 多个DOUBLE相乘，解决精度问题
     * <p>
     * ，返回-
     *
     * @return 参数个数为0时，返回0；参数个数为1时，返回这个参数；参数个数为多个时，返回其中值不为null的参数的连乘结果；为null的参数视为0
     */
    public static Double multiply(Number... nums) {
        if (nums.length == 0)
            return 0.0;
        if (nums.length == 1) {
            return nums[0].doubleValue();
        }
        BigDecimal result = new BigDecimal(1);

        for (Number n : nums) {
            //null值视为0
            if (null == n) {
                n = 0;
            }
            //如果有参数为0，则结果为0；
            if (0 == n) {
                return 0.0;
            }
            result = result.multiply(new BigDecimal(n.toString()));

        }

        return result.doubleValue();
    }


}
